package com.web.controller.pay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.internal.util.WebUtils;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.google.gson.JsonObject;
import com.xkk.utils.GSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 蚂蚁金服 支付
 * Created by xukk on 2017/7/4.
 */
@Slf4j
public class AliPayManage {
    public static AliPayManage mg = new AliPayManage();

    /**
     * 扫码支付
     * @param payCodeDto
     * @return
     */
    public PayResponse aliPayCode(AliPayDto payCodeDto) {
        AlipayClient alipayClient = new DefaultAlipayClient(payCodeDto.getPayUrl(), payCodeDto.getPayAppid(), payCodeDto.getPaySelfSecret(), "json", "utf-8", payCodeDto.getPayPublicSecret2(), "RSA2");
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        if (payCodeDto.getNotifyUrl() != null)
            request.setNotifyUrl(payCodeDto.getNotifyUrl());
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("out_trade_no", payCodeDto.getOutTradeNo());
        jsonObject.addProperty("total_amount", payCodeDto.getTotalAmount());
        jsonObject.addProperty("subject", payCodeDto.getSubject());
        if (payCodeDto.getSellerId() != null)
            jsonObject.addProperty("seller_id", payCodeDto.getSellerId());
        if (payCodeDto.getBody() != null)
            jsonObject.addProperty("body", payCodeDto.getBody());
        String content = jsonObject.toString();
        log.info("ali payCode data->{}", content);
        request.setBizContent(content);
        AlipayTradePrecreateResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            log.warn("ali payCode AlipayApiException error->{}", e.getMessage());
            return PayResponse.custom().failure(e.getMessage());
        } catch (Exception e) {
            log.warn("ali payCode AlipayApiException error->{}", e.getMessage());
            return PayResponse.custom().failure(e.getMessage());
        }
        log.info("ali payCode response->{}", GSONUtil.toJson(response));
        if (response.isSuccess()) {
            return PayResponse.custom().addParams(response).ok();
        } else {
            return PayResponse.custom().failure(response.getSubMsg());
        }
    }

    /**
     * APP支付
     * @param payCodeDto
     * @return
     */
    public PayResponse aliPayApp(AliPayDto payCodeDto) {
        AlipayClient alipayClient = new DefaultAlipayClient(payCodeDto.getPayUrl(), payCodeDto.getPayAppid(), payCodeDto.getPaySelfSecret(), "json", "utf-8", payCodeDto.getPayPublicSecret2(), "RSA2");
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        if (StringUtils.isNotBlank(payCodeDto.getBody()))
            model.setBody(payCodeDto.getBody());
        if(StringUtils.isNotBlank(payCodeDto.getSellerId()))
        model.setSellerId(payCodeDto.getSellerId());
        model.setSubject(payCodeDto.getSubject());
        model.setOutTradeNo(payCodeDto.getOutTradeNo());
        if (StringUtils.isNotBlank(payCodeDto.getTimeOutExpress()))
            model.setTimeoutExpress(payCodeDto.getTimeOutExpress());
        request.setNotifyUrl(payCodeDto.getNotifyUrl());
        if (StringUtils.isNotBlank(payCodeDto.getProductCode()))
            model.setProductCode(payCodeDto.getProductCode());
        else model.setProductCode("QUICK_MSECURITY_PAY");
        log.info("ali appCode data->{}", GSONUtil.toJson(model));
        request.setBizModel(model);
        model.setTotalAmount(payCodeDto.getTotalAmount());
        AlipayTradeAppPayResponse response = null;
        try {
            response = alipayClient.sdkExecute(request);
        } catch (AlipayApiException e) {
            log.warn("ali appCode AlipayApiException error->{}", e.getErrMsg());
            return PayResponse.custom().failure(e.getErrMsg());
        } catch (Exception e) {
            log.warn("ali appCode Exception error->{}", e.getMessage());
            return PayResponse.custom().failure(e.getMessage());
        }
        log.info("ali appCode response->{}", GSONUtil.toJson(response));
        if (response.isSuccess()) {
            return PayResponse.custom().addParams(response).ok();
        } else {
            return PayResponse.custom().failure(response.getSubMsg());
        }
    }

    /**
     * 取消支付
     * @param payCodeDto
     * @return
     */
    public PayResponse aliCancel(AliPayDto payCodeDto) {
        AlipayClient alipayClient = new DefaultAlipayClient(payCodeDto.getPayUrl(), payCodeDto.getPayAppid(), payCodeDto.getPaySelfSecret(), "json", "utf-8", payCodeDto.getPayPublicSecret(), "RSA");
        AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
        if (StringUtils.isBlank(payCodeDto.getTradeNo()) && StringUtils.isBlank(payCodeDto.getOutTradeNo())) {
            return PayResponse.custom().failure("tradeNo,outTradeNo 不能同时为空");
        }
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("out_trade_no", payCodeDto.getOutTradeNo());
        jsonObject.addProperty("trade_no", payCodeDto.getTradeNo());
        request.setBizContent(jsonObject.toString());
        AlipayTradeCancelResponse response = null;
        try {
            response = alipayClient.execute(request);
            log.info("ali cancel response->{}", GSONUtil.toJson(response));
        } catch (AlipayApiException e) {
            log.warn("ali cancel AlipayApiException error->{}", e.getErrMsg());
            return PayResponse.custom().failure(e.getErrMsg());
        } catch (Exception e) {
            log.warn("ali cancel AlipayApiException error->{}", e.getMessage());
            return PayResponse.custom().failure(e.getMessage());
        }
        if (response.isSuccess()) {
            return PayResponse.custom().addParams(response).ok();
        } else {
            return PayResponse.custom().failure(response.getSubMsg());
        }
    }

    /**
     * 退款
     * @param payCodeDto
     * @return
     */
    public PayResponse aliRefund(AliPayDto payCodeDto) {
        AlipayClient alipayClient = new DefaultAlipayClient(payCodeDto.getPayUrl(), payCodeDto.getPayAppid(), payCodeDto.getPaySelfSecret(), "json", "utf-8", payCodeDto.getPayPublicSecret(), "RSA2");
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        if (StringUtils.isBlank(payCodeDto.getRefundAmount())) {
            return PayResponse.custom().failure("refundAmount 不为空");
        }
        if (StringUtils.isNotBlank(payCodeDto.getOutTradeNo()) && StringUtils.isNotBlank(payCodeDto.getTradeNo())){
            return PayResponse.custom().failure("out_trade_no,trade_no 两者不能同时为空");
        }
//        if (StringUtils.isNoneBlank(payCodeDto.getOutTradeNo(), payCodeDto.getTradeNo())) {
//            return PayResponse.custom().failure("out_trade_no,trade_no 两者不能同时为空");
//        }
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("out_trade_no", payCodeDto.getOutTradeNo());
        jsonObject.addProperty("trade_no", payCodeDto.getTradeNo());
        jsonObject.addProperty("refund_amount", payCodeDto.getRefundAmount());
        jsonObject.addProperty("refund_reason", payCodeDto.getRefundReason());
        String content = jsonObject.toString();
        log.info("ali refund data->{}", content);
        request.setBizContent(content);
        AlipayTradeRefundResponse response = null;
        try {
            response = alipayClient.execute(request);
            log.info("ali refund response->{}", GSONUtil.toJson(response));
        } catch (AlipayApiException e) {
            log.warn("ali refund AlipayApiException error->{}", e.getErrMsg());
            return PayResponse.custom().failure(e.getErrMsg());
        } catch (Exception e) {
            log.warn("ali refund Exception error->{}", e.getMessage());
            return PayResponse.custom().failure(e.getMessage());
        }
        if (response.isSuccess()) {
            return PayResponse.custom().addParams(response).ok();
        } else {
            return PayResponse.custom().failure(response.getSubMsg());
        }
    }

    /**
     * 校验Url 返回值
     *
     * @param payCodeDto
     * @return
     */
    public PayResponse aliValid(AliPayDto payCodeDto) {
        Map map = null;
        if (payCodeDto.getJson() != null)
            map = WebUtils.splitUrlQuery(WebUtils.decode(payCodeDto.getJson()));
        else map = payCodeDto.getMap();

//        map.put("sign", Base64.encodeBase64String(map.get("sign").toString().getBytes()));
        log.info("ali_notify_result_valid map:{}", map);
        String publicSecret = null;
        if (map.get("sign_type").equals("RSA2"))
            publicSecret = payCodeDto.getPayPublicSecret2();
        else publicSecret = payCodeDto.getPayPublicSecret();
        try {
            if (AlipaySignature.rsaCheckV1(map, publicSecret, "utf-8", map.get("sign_type").toString())) {
                return PayResponse.Map(map).ok();
            } else {
                log.info("------------->>>>> :    ali 校验失败!");
                return PayResponse.custom().failure("ali 校验失败!");
            }
        } catch (AlipayApiException e) {
            log.warn("AlipayApiException 错误:{}", e.getErrMsg());
            return PayResponse.custom().failure(e.getErrMsg());
        }
    }

    public Boolean test(HttpServletRequest request, String alipaypublicKey) throws Exception{
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);

        }
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        boolean flag = AlipaySignature.rsaCheckV1(params, alipaypublicKey, "utf-8","RSA2");
        return flag;
    }
}
